package tech.waterism.topo.context;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import tech.waterism.topo.model.*;

import java.util.*;

import static org.junit.jupiter.api.Assertions.*;

/**
 * CalculationContext 单元测试
 * 
 * @author waterism
 * @since 1.0.0
 */
class CalculationContextTest {
    
    private CalculationContext context;
    
    @BeforeEach
    void setUp() {
        context = new CalculationContext();
    }
    
    @Test
    void testInitialization() {
        // 验证初始化状态
        assertNotNull(context.getResultCache());
        assertNotNull(context.getJointResultCache());
        assertNotNull(context.getHubDistributionCache());
        assertNotNull(context.getNodeIndexMap());
        assertNotNull(context.getJointTriggerMap());
        assertNotNull(context.getJointGroupMap());
        assertNotNull(context.getJointGroups());
    }
    
    @Test
    void testCacheResult() {
        // 准备
        NodeResult result = new NodeResult("NODE01", new ArrayList<>());
        
        // 执行
        context.cacheResult("NODE01", result);
        
        // 验证
        assertTrue(context.isCached("NODE01"));
        assertEquals(result, context.getCachedResult("NODE01"));
    }
    
    @Test
    void testIsCached_NotCached() {
        // 验证未缓存的节点
        assertFalse(context.isCached("UNKNOWN"));
        assertNull(context.getCachedResult("UNKNOWN"));
    }
    
    @Test
    void testCacheJointResult() {
        // 准备
        NodeResult result = new NodeResult("JOINT01", new ArrayList<>());
        
        // 执行
        context.cacheJointResult("JOINT01", result);
        
        // 验证：联调缓存中应该有，但主缓存中没有
        assertFalse(context.isCached("JOINT01"));
        assertEquals(result, context.getJointResultCache().get("JOINT01"));
    }
    
    @Test
    void testMergeJointResults() {
        // 准备：在联调缓存中添加结果
        NodeResult result1 = new NodeResult("JOINT01", new ArrayList<>());
        NodeResult result2 = new NodeResult("JOINT02", new ArrayList<>());
        context.cacheJointResult("JOINT01", result1);
        context.cacheJointResult("JOINT02", result2);
        
        // 验证：主缓存中没有
        assertFalse(context.isCached("JOINT01"));
        assertFalse(context.isCached("JOINT02"));
        
        // 执行合并
        context.mergeJointResults();
        
        // 验证：主缓存中应该有
        assertTrue(context.isCached("JOINT01"));
        assertTrue(context.isCached("JOINT02"));
        assertEquals(result1, context.getCachedResult("JOINT01"));
        assertEquals(result2, context.getCachedResult("JOINT02"));
        
        // 联调缓存应该被清空
        assertTrue(context.getJointResultCache().isEmpty());
    }
    
    @Test
    void testNodeIndexMap() {
        // 添加节点索引
        context.getNodeIndexMap().put("NODE01", 0);
        context.getNodeIndexMap().put("NODE02", 1);
        context.getNodeIndexMap().put("NODE03", 2);
        
        // 验证
        assertEquals(0, context.getNodeIndex("NODE01"));
        assertEquals(1, context.getNodeIndex("NODE02"));
        assertEquals(2, context.getNodeIndex("NODE03"));
        assertNull(context.getNodeIndex("UNKNOWN"));
    }
    
    @Test
    void testHubDistribution() {
        // 准备
        List<TimeSeriesData> data = new ArrayList<>();
        TimeSeriesData d1 = new TimeSeriesData();
        d1.setQ(100.0);
        data.add(d1);
        
        // 添加枢纽分流数据
        context.addHubDistribution("HUB01", data);
        
        // 验证
        assertTrue(context.hasHubDistribution("HUB01"));
        assertEquals(data, context.getHubDistribution("HUB01"));
        
        // 不存在的枢纽
        assertFalse(context.hasHubDistribution("UNKNOWN"));
        assertNull(context.getHubDistribution("UNKNOWN"));
    }
    
    @Test
    void testTriggeredGroup() {
        // 准备
        JointDispatchGroup group = new JointDispatchGroup();
        group.setJmsid(1);
        group.setName("联调组1");
        context.getJointGroupMap().put(1, group);
        
        // 初始状态：没有触发的联调组
        assertFalse(context.hasTriggeredGroup());
        
        // 设置触发的联调组
        context.setTriggeredGroup(1);
        
        // 验证
        assertTrue(context.hasTriggeredGroup());
        assertNotNull(context.getTriggeredGroup());
        assertEquals(1, context.getTriggeredGroup().getJmsid());
        
        // 清除触发的联调组
        context.clearTriggeredGroup();
        assertFalse(context.hasTriggeredGroup());
    }
    
    @Test
    void testTimeParameters() {
        // 设置时间参数
        Date startTime = new Date();
        Date obsTime = new Date(startTime.getTime() - 3600000);
        Date modifyTime = new Date(startTime.getTime() + 3600000);
        
        context.setStartTime(startTime);
        context.setObservationStartTime(obsTime);
        context.setModifyTime(modifyTime);
        
        // 验证
        assertEquals(startTime, context.getStartTime());
        assertEquals(obsTime, context.getObservationStartTime());
        assertEquals(modifyTime, context.getModifyTime());
    }
    
    @Test
    void testDispatchConfiguration() {
        // 设置调度配置
        context.setDispatchType(3);
        context.setOutFlowType(1);
        context.setUseHydro(true);
        
        // 验证
        assertEquals(3, context.getDispatchType());
        assertEquals(1, context.getOutFlowType());
        assertTrue(context.getUseHydro());
    }
    
    @Test
    void testNodes() {
        // 创建节点列表
        List<TopoNode> nodes = new ArrayList<>();
        TopoNode node1 = new TopoNode();
        node1.setStcd("NODE01");
        TopoNode node2 = new TopoNode();
        node2.setStcd("NODE02");
        nodes.add(node1);
        nodes.add(node2);
        
        // 设置节点
        context.setNodes(nodes);
        
        // 验证
        assertNotNull(context.getNodes());
        assertEquals(2, context.getNodes().size());
        assertEquals("NODE01", context.getNodes().get(0).getStcd());
        assertEquals("NODE02", context.getNodes().get(1).getStcd());
    }
    
    @Test
    void testJointGroups() {
        // 创建联调组
        List<JointDispatchGroup> groups = new ArrayList<>();
        JointDispatchGroup group1 = new JointDispatchGroup();
        group1.setJmsid(1);
        JointDispatchGroup group2 = new JointDispatchGroup();
        group2.setJmsid(2);
        groups.add(group1);
        groups.add(group2);
        
        // 设置联调组
        context.setJointGroups(groups);
        
        // 验证
        assertNotNull(context.getJointGroups());
        assertEquals(2, context.getJointGroups().size());
    }
    
    @Test
    void testJointTriggerMap() {
        // 添加触发条件
        context.getJointTriggerMap().put(1, Arrays.asList("NODE01", "NODE02"));
        context.getJointTriggerMap().put(2, Arrays.asList("NODE03", "NODE04"));
        
        // 验证
        assertTrue(context.getJointTriggerMap().containsKey(1));
        assertTrue(context.getJointTriggerMap().containsKey(2));
        assertEquals(2, context.getJointTriggerMap().get(1).size());
    }
    
    @Test
    void testMultipleCacheOperations() {
        // 准备多个结果
        NodeResult result1 = new NodeResult("NODE01", new ArrayList<>());
        NodeResult result2 = new NodeResult("NODE02", new ArrayList<>());
        NodeResult result3 = new NodeResult("NODE03", new ArrayList<>());
        
        // 缓存到主缓存
        context.cacheResult("NODE01", result1);
        context.cacheResult("NODE02", result2);
        
        // 缓存到联调缓存
        context.cacheJointResult("NODE03", result3);
        
        // 验证
        assertTrue(context.isCached("NODE01"));
        assertTrue(context.isCached("NODE02"));
        assertFalse(context.isCached("NODE03"));
        
        // 合并后验证
        context.mergeJointResults();
        assertTrue(context.isCached("NODE03"));
    }
}

